package com.yanling.mybatis.executor;

import com.sun.deploy.util.ReflectionUtil;
import com.yanling.mybatis.mapping.MappedStatement;
import com.yanling.mybatis.session.Configuration;
import lombok.extern.slf4j.Slf4j;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @description: Executor 接口的实现类，主要是对 JDBC 的封装，和利用反射方法将结果映射到 resultType 对应的实体类中
 * @author: yanling
 * @time: 2021/1/1 21:46
 */
@Slf4j
public class SimpleExecutor implements Executor {

	private final Configuration configuration;

	public SimpleExecutor(Configuration configuration) {
		this.configuration = configuration;
	}



	@Override
	public <E> List<E> query(MappedStatement ms, Object parameter) {
		log.info("当前的sql：" + ms.getSql());
		List<E> ret = new ArrayList<>(); //返回结果集
		try {
			Class.forName(configuration.getJdbcDriver());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		try {
			connection = DriverManager.getConnection(configuration.getJdbcUrl(), configuration.getJdbcUsername(), configuration.getJdbcPassword());
			String regex = "#\\{([^}])*\\}";
			// 将 sql 语句中的 #{userId} 替换为 ？
			String  sql = ms.getSql().replaceAll(regex,"?");
			preparedStatement = connection.prepareStatement(sql);
			//处理占位符，把占位符用传入的参数替换
			parametersize(preparedStatement, parameter);
			log.info("当前的sql：" + preparedStatement.getConnection().getMetaData().getSQLKeywords());
			resultSet = preparedStatement.executeQuery();
			try {
				Class resultType = Class.forName(ms.getResultType());
				handlerResultSet(resultSet, ret, resultType);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}catch (SQLException e){
			e.printStackTrace();
		}finally {
			try {
				resultSet.close();
				preparedStatement.close();
				connection.close();
			}catch (Exception e){
				e.printStackTrace();
			}
		}

		return ret;
	}

	private void parametersize(PreparedStatement preparedStatement,Object parameter) throws SQLException{
		if(parameter instanceof Integer){
			preparedStatement.setInt(1,(int)parameter);
		}else if(parameter instanceof  Long){
			preparedStatement.setLong(1,(Long)parameter);
		}else if(parameter instanceof  String){
			preparedStatement.setString(1,(String)parameter);
		}
	}

	private <E> void handlerResultSet(ResultSet resultSet, List<E> ret,Class<E> clazz){
		E obj = null;

		try {
			// 获得结果集的元数据信息(包含列的数量，列的名称)
			ResultSetMetaData rsmd = resultSet.getMetaData();
			// 获得结果集中列的数量
			int columnCount = rsmd.getColumnCount();
			List<Object> labelList = new ArrayList<>(columnCount);
			for(int i=0;i<columnCount;i++) {
				// 将所有的列别名遍历出来，存入数组中
				labelList.add(rsmd.getColumnLabel(i+1).toUpperCase());
			}

			while (resultSet.next()) {
				obj = clazz.newInstance();

				// 遍历属性描述器，
				for (int i = 0; i < columnCount; i++) {
					String name = rsmd.getColumnLabel(i + 1);
					Field field = obj.getClass().getDeclaredField(name);// 获得属性名
					field.setAccessible(true);
					// 将结果集中的值赋给相应的对象实体的属性
					field.set(obj, resultSet.getObject(name));
				}
				// 将对象存入集合
				ret.add(obj);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}



}
